home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / SAT / HeartQuest sample ƒ / scores.p < prev    next >
Encoding:
Text File  |  1994-07-26  |  12.5 KB  |  467 lines  |  [TEXT/PJMM]

  1. {================================================}
  2. {============= Score handling and display ==============}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { This file manages the display and update of the game scores for HeartQuest.}
  10. { It holds routines for updating high score list, including asking for the name of}
  11. { the player, high score window etc. When making a new game, you will probably}
  12. { need to rewrite this unit a lot. }
  13.  
  14. unit scores;
  15.  
  16. interface
  17.     uses
  18.         transskel, SAT, Preferences, GameGlobals, SoundConst, CenterStuff;
  19.  
  20.     var
  21.         score: longint;
  22.  
  23.     procedure DoHighMenu (item: integer);
  24.     procedure InitScores;                    { Loads the high score list and the high score window. }
  25.     procedure ZeroScore;                     { Call this on New Game! }
  26.     procedure AddScore (amount: longint);    { Call this when the player gets points, or with addscore(0) just to redisplay. }
  27.     procedure AddScoreS (amount: longint);    { Call this to redisplay when the animation isn't running. }
  28.     procedure UpdateHigh;                    { Call this on game over! }
  29.  
  30. implementation
  31.  
  32. { Highscore record }
  33.     type
  34.         hsRec = record
  35.                 HighScores: array[0..10] of longint;
  36.                 HighPlayer: array[0..10] of str15;
  37.             end;
  38.         hsPtr = ^hsRec;
  39.         hsHnd = ^hsPtr;
  40.  
  41.  
  42.     var
  43.         hs, hsm: hsHnd; { m is for macho mode }
  44.         hsh, hshm: Handle;
  45.  
  46. { Bitmaps and rects for drawhex }
  47. {    srcr, erasr: Rect;}
  48. {    bm: BitMap;}
  49. {    icon: Handle;}
  50. {    bma: array[0..9] of BitMap;}
  51. {    icons: array[0..9] of Handle;}
  52.  
  53. {Filter function for AskHigh, ok = 1 and cancel = 4}
  54.     function Filter (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: integer): boolean;
  55.         var
  56.             theChar: Char;
  57.             kind: integer;
  58.             item: Handle;
  59.             box: Rect;
  60.     begin
  61.         if theEvent.what = keyDown then
  62.             begin
  63.                 theChar := Char(BitAnd(theEvent.message, charCodeMask));
  64.                 if BitAnd(theEvent.modifiers, cmdkey) <> 0 then
  65.                     if theChar = '.' then
  66.                         begin
  67.                             itemHit := 4;
  68. {Highlight the cancel button}
  69.                             GetDItem(theDialog, 4, kind, item, box);
  70.                             HiliteControl(ControlHandle(item), 1);
  71.  
  72.                             Filter := true;
  73.                             exit(Filter);
  74.                         end;
  75.                 if (theChar = char(13)) or (theChar = char(3)) then
  76.                     begin
  77.                         itemHit := 1;
  78. {Highlight the OK button}
  79.                         GetDItem(theDialog, 1, kind, item, box);
  80.                         HiliteControl(ControlHandle(item), 1);
  81.  
  82.                         Filter := true;
  83.                         exit(Filter);
  84.                     end;
  85.             end;
  86.         Filter := false;
  87.     end;
  88.  
  89. {Put a frame around a dialog item. There are better ways to do this, though. The right way}
  90. {is to draw the frame as response to an update event, not just when opening the dialog.}
  91.     procedure FrameDItem (dLog: DialogPtr; iNum: integer);
  92.         var
  93.             iBox: Rect;
  94.             iType: integer;
  95.             iHandle: Handle;
  96.             oldPenState: PenState;
  97.             tmpp: GrafPtr;
  98.     begin
  99.         GetPort(tmpp);
  100.         SetPort(dLog);
  101.         GetPenState(oldPenState);
  102.         GetDItem(dLog, iNum, iType, iHandle, iBox);
  103.         InsetRect(iBox, -4, -4);
  104.         PenSize(3, 3);
  105.         FrameRoundRect(iBox, 16, 16);
  106.         SetPenState(oldPenState);
  107.         SetPort(tmpp);
  108.     end;
  109.  
  110. { Ask for players name (at highscore) }
  111.     function AskHigh: str255;
  112.         var
  113.             dialog: DialogPtr;
  114.             oldPort: GrafPtr;
  115.             dRec: DialogRecord;
  116.             itemHit: integer;
  117.             itemHandle: Handle;
  118.             itemType, item: integer;
  119.             itemRect: Rect;
  120.             str: str255;
  121.             levelstr: str255;
  122.     begin
  123.         CenterDialog(highDlog);
  124.         GetPort(oldPort);
  125.         dialog := GetNewDialog(highDlog, @dRec, WindowPtr(-1));
  126.         ShowWindow(dialog);
  127.         SelectWindow(dialog);
  128.         SetPort(dialog);
  129.  
  130.         GetDItem(dialog, 3, itemType, itemHandle, itemRect);
  131.         SetIText(itemHandle, features^^.player);
  132.         SelIText(dialog, 3, 0, 32767);
  133.         FrameDItem(dialog, 1);
  134.         itemHit := -1;
  135.         while (itemHit <> 1) and (itemHit <> 4) do { 1=ok, 4=cancel }
  136.             ModalDialog(@Filter, itemHit);
  137.         if itemHit = 4 then
  138.             begin
  139.                 AskHigh := '';
  140.             end;
  141.         if itemHit = 1 then
  142.             begin
  143.                 GetDItem(dialog, 3, itemType, itemHandle, itemRect);
  144.                 GetIText(itemHandle, str);
  145.                 if length(str) > 15 then
  146.                     str := Copy(str, 1, 15);
  147.                 features^^.player := str;
  148.                 AskHigh := str;
  149.             end;
  150.         CloseDialog(dialog);
  151.         SetPort(oldPort);
  152.     end;
  153.  
  154. {     High Score window handlers }
  155.  
  156.     procedure HighUpdate (resized: boolean);
  157.         var
  158.             s: str255;
  159.             i: integer;
  160.     begin
  161.         EraseRect(theHigh^.portrect);
  162.         TextSize(9);
  163.  
  164.         moveto(10, 20);
  165.         DrawString(MyGetIndString(normalStrID)); {str 9: Normal high score list}
  166.         MoveTo(150, 20);
  167.         DrawString(MyGetIndString(machoStrID)); {str 10: Macho high score list}
  168.         MoveTo(0, 22);
  169.         LineTo(500, 22);
  170.         MoveTo(140, 0);
  171.         LineTo(140, 400);
  172.  
  173.         for i := 1 to 10 do
  174.             begin
  175.                 if not LastMacho and (i = LastHigh) then
  176.                     begin
  177.                         TextFace([bold]);
  178.                         ForeColor(redColor);
  179.                     end;
  180.                 moveto(10, i * 18 + 20);
  181.                 DrawString(hs^^.HighPlayer[i]);
  182.                 moveto(110, i * 18 + 20);
  183.                 NumToString(hs^^.HighScores[i], s);
  184.                 DrawString(s);
  185.  
  186.                 TextFace([]);
  187.                 ForeColor(BlackColor);
  188.                 if LastMacho and (i = LastHigh) then
  189.                     begin
  190.                         TextFace([bold]);
  191.                         ForeColor(redColor);
  192.                     end;
  193.                 moveto(150, i * 18 + 20);
  194.                 DrawString(hsm^^.HighPlayer[i]);
  195.                 moveto(250, i * 18 + 20);
  196.                 NumToString(hsm^^.HighScores[i], s);
  197.                 DrawString(s);
  198.  
  199.                 TextFace([]);
  200.                 ForeColor(BlackColor);
  201.             end;
  202.         TextSize(12);
  203.     end;
  204.  
  205.     procedure HighHalt;
  206.     begin
  207.         CloseWindow(theHigh);
  208.     end;
  209.  
  210.     function InternalAddScore (amount: longint): Rect;
  211.         var
  212.             s: str255;
  213.             r: Rect;
  214.     begin
  215.         score := score + amount;
  216.  
  217.         SetPort(gSAT.backScreen);
  218.         SetRect(r, gSAT.offSizeH - 49, 14, gSAT.offSizeH - 2, 155);
  219.         EraseRoundRect(r, 10, 10);
  220.         FrameRoundRect(r, 10, 10);
  221.         NumToString(Score, s);
  222.         MoveTo(gSAT.offSizeH - 47, 30);
  223.         DrawString(MyGetIndString(scoreStrID)); {str 11: Score: }
  224.         MoveTo(gSAT.offSizeH - 47, 50);
  225.         DrawString(s);
  226.  
  227.         NumToString(bonus, s);
  228.         MoveTo(gSAT.offSizeH - 47, 80);
  229.         DrawString(MyGetIndString(bonusStrID)); {str 12: Bonus: }
  230.         MoveTo(gSAT.offSizeH - 47, 100);
  231.         DrawString(s);
  232.  
  233.         NumToString(Level, s);
  234.         MoveTo(gSAT.offSizeH - 47, 130);
  235.         DrawString(MyGetIndString(levelStrID)); {str 13: Level: }
  236.         MoveTo(gSAT.offSizeH - 47, 150);
  237.         DrawString(s);
  238.         InternalAddScore := r;
  239.     end;
  240.  
  241.     procedure AddScore (amount: longint);
  242.         var
  243.             s: str255;
  244.             r: Rect;
  245.             tmpport: grafptr;
  246.     begin
  247.         GetPort(tmpPort);
  248.         r := InternalAddScore(amount);
  249.         SATBackChanged(r); {Let SAT show it on screen}
  250.         SetPort(tmpPort);
  251.     end;
  252.  
  253.     procedure AddScoreS (amount: longint);
  254.         var
  255.             s: str255;
  256.             r: Rect;
  257.             tmpport: grafptr;
  258.     begin
  259.         GetPort(tmpPort);
  260.         r := InternalAddScore(amount);
  261.         CopyBits(gSAT.backScreen^.portbits, gSAT.wind^.portBits, r, r, srcCopy, nil);
  262.         CopyBits(gSAT.backScreen^.portbits, gSAT.offScreen^.portBits, r, r, srcCopy, nil);
  263.         SetPort(tmpPort);
  264.     end;
  265.  
  266.     procedure DoHighMenu (item: integer);
  267.         var
  268.             p: procptr;
  269.             i: integer;
  270.     begin
  271.         case item of
  272.             showhs: 
  273.                 begin
  274.                     ShowWindow(theHigh);
  275.                     SelectWindow(theHigh);
  276.                 end;
  277.             clearhs: 
  278.                 begin
  279.                     if QuestionStr(MyGetIndString(sureStrID)) then {str 14: Are you sure you want to erase the high scores?}
  280.                         begin
  281.                             for i := 1 to 10 do
  282.                                 begin
  283.                                     hs^^.HighScores[i] := 0;            { skall läsas från fil eller resurs }
  284.                                     hs^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15: Nobody}
  285.                                     hsm^^.HighScores[i] := 0;            { skall läsas från fil eller resurs }
  286.                                     hsm^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15}
  287.                                 end;
  288.                             hs^^.HighScores[0] := 10000;            { Lowscore }
  289.                             hsm^^.HighScores[0] := 10000;            { Lowscore }
  290.                             ChangedResource(handle(hs));
  291.                             ChangedResource(handle(hsm));
  292.                             HideWindow(theHigh);
  293.                         end;
  294.                 end;
  295.             otherwise
  296.                 ;
  297.         end;
  298.     end;
  299.  
  300.     procedure WindKey (theChar: char; theMods: integer);
  301.     begin
  302.     end;
  303.  
  304. { Call this on game over! }
  305.     procedure UpdateHigh;
  306.         var
  307.             num, len: integer;
  308.             name, s: str255;
  309.     begin
  310.         lastMacho := features^^.macho;
  311.  
  312.         if features^^.macho then
  313.             begin
  314.                 if score > hsm^^.HighScores[10] then
  315.                     begin
  316.                         num := 10;
  317.                         name := AskHigh;
  318.                         NumToString(level, s); {used below, to append level number}
  319. {Max 15 characters! We take some extra trouble to append '…' too.}
  320.                         len := length(stringof(' (', s, ')'));
  321.                         if length(name) > 15 - len then
  322.                             name := Concat(Copy(name, 1, 15 - len - 1), '…');
  323.  
  324.                         if name = '' then { alt length(name) = 0 }
  325.                             exit(updatehigh);
  326.                         while (hsm^^.HighScores[num - 1] < score) and (num > 1) do
  327.                             begin
  328.                                 hsm^^.HighScores[num] := hsm^^.HighScores[num - 1];
  329.                                 hsm^^.HighPlayer[num] := hsm^^.HighPlayer[num - 1];
  330.                                 num := num - 1;
  331.                             end;
  332.                         LastHigh := num; {Remember last high for the highscore display}
  333.                         hsm^^.HighScores[num] := score;
  334.                         hsm^^.HighPlayer[num] := stringof(name, ' (', s, ')'); {AskHigh;}
  335.                         ChangedResource(handle(hsm));
  336.                         HideWindow(theHigh);
  337.                         ShowWindow(theHigh);
  338.                         SelectWindow(theHigh);
  339.                     end;
  340.             end{ if macho }
  341.         else if score > hs^^.HighScores[10] then
  342.             begin
  343.                 num := 10;
  344.                 name := AskHigh;
  345.                 if length(name) > 15 then
  346.                     name := Concat(Copy(name, 1, 14), '…');
  347.  
  348.                 if name = '' then { alt length(name) = 0 }
  349.                     exit(updatehigh);
  350.                 while (hs^^.HighScores[num - 1] < score) and (num > 1) do
  351.                     begin
  352.                         hs^^.HighScores[num] := hs^^.HighScores[num - 1];
  353.                         hs^^.HighPlayer[num] := hs^^.HighPlayer[num - 1];
  354.                         num := num - 1;
  355.                     end;
  356.                 LastHigh := num; {Remember last high for the highscore display}
  357.                 hs^^.HighScores[num] := score;
  358.                 hs^^.HighPlayer[num] := name;
  359.                 ChangedResource(handle(hs));
  360.                 HideWindow(theHigh);
  361.                 ShowWindow(theHigh);
  362.                 SelectWindow(theHigh);
  363.             end;
  364.     end;
  365.  
  366.     procedure ZeroScore;
  367.     begin
  368.         score := 0;
  369.         LastHigh := -1;
  370.     end;
  371.  
  372. {This procedure copies a resource from the file applFile to prefFile (global file numbers,}
  373. {from the unit Preferences).}
  374. {OBSOLETE - should be replaced by the better code in Preferences.p!}
  375.     procedure OldCopyResource (resType: OSType; id: integer);
  376.         var
  377.             h, h2: Handle;
  378.             saveFile: integer;
  379.     begin
  380.         saveFile := CurResFile; {Look where we are so we can restore}
  381.         UseResFile(gAppFile);
  382.  
  383.         h := GetResource(resType, id); {Get res from the appl}
  384.         if h <> nil then
  385.             begin
  386.                 UseResFile(gPrefFile);
  387.                 h2 := GetResource(resType, id);
  388.                 if h2 = nil then {It doesn't already exist}
  389.                     begin
  390.                         DetachResource(h); {Detach it so we can move it.}
  391.                         AddResource(h, resType, id, ''); {Put it into the gPrefFile}
  392.                         ReleaseResource(h);
  393.                     end
  394.                 else {The res always exists. Don't copy.}
  395.                     begin
  396.                         ReleaseResource(h);
  397.                         ReleaseResource(h2);
  398.                     end;
  399.             end;
  400.         UseResFile(saveFile); {restore}
  401.     end;
  402.  
  403.     procedure InitScores;
  404.         var
  405.             i: integer;
  406.             ignoreErr: OSErr;
  407.     begin
  408.         if SetPrefFile(kPrefsFileName, kPrefCreator, kPrefType, false) then {If a pref file was created, copy high scores to it!}
  409.             begin
  410. {CopyResource('Bäst', 0); {Normal mode high scores}
  411. {CopyResource('Bäst', 1); {Macho mode high scores}
  412. {CopyResource('Feat', 0); {Settings}
  413.                 ignoreErr := CopyResource(gAppFile, gPrefFile, 'Bäst', 0); {Normal mode high scores}
  414.                 ignoreErr := CopyResource(gAppFile, gPrefFile, 'Bäst', 1); {Macho mode high scores}
  415.                 ignoreErr := CopyResource(gAppFile, gPrefFile, 'Feat', 0); {Settings}
  416.             end
  417.         else
  418.             gPrefFile := gAppFile; {If we have no pref file, let's make sure we UseResFile to something that exists.}
  419.  
  420.         lastHigh := -1; {no "last"}
  421.  
  422.         theHigh := GetNewWindow(theHighRes, nil, WindowPtr(-1));
  423.         SetPort(theHigh);
  424.         dummy := SkelWindow(theHigh, nil, @WindKey, @HighUpdate, nil, nil, @HighHalt, nil, false);
  425.  
  426.         UseResFile(gPrefFile); {set the resfile to the pref file, if any. If none, gPrefFile will be the app itself!}
  427.  
  428.         hs := hsHnd(GetResource('Bäst', 0));
  429.         if hs = nil then {Didn't exist - create it!}
  430.             begin
  431.                 hs := hsHnd(NewHandle(Sizeof(hsRec)));
  432.                 CheckNoMem(Ptr(hs));
  433.                 for i := 1 to 10 do
  434.                     begin
  435.                         hs^^.HighScores[i] := 0;
  436.                         hs^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15}
  437.                     end;
  438.                 hs^^.HighScores[0] := 10000;            { Lowscore }
  439.                 AddResource(handle(hs), 'Bäst', 0, 'High scores');
  440.             end
  441.         else {Did exist - check the size!}
  442.             if GetHandleSize(Handle(hs)) < sizeof(hsHnd) then
  443.                 SetHandleSize(Handle(hs), sizeof(hsHnd));
  444.  
  445.         hsm := hsHnd(GetResource('Bäst', 1));
  446.         if hsm = nil then {Didn't exist - create it!}
  447.             begin
  448.                 hsm := hsHnd(NewHandle(Sizeof(hsRec)));
  449.                 CheckNoMem(Ptr(hsm));
  450.                 for i := 1 to 10 do
  451.                     begin
  452.                         hsm^^.HighScores[i] := 0;            { skall läsas från fil eller resurs }
  453.                         hsm^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15}
  454.                     end;
  455.                 hsm^^.HighScores[0] := 10000;            { Lowscore }
  456.                 AddResource(handle(hsm), 'Bäst', 1, 'High scores');
  457.             end
  458.         else {Did exist - check the size!}
  459.             if GetHandleSize(Handle(hsm)) < sizeof(hsHnd) then
  460.                 SetHandleSize(Handle(hsm), sizeof(hsHnd));
  461.  
  462.         UseResFile(gAppFile);
  463.  
  464.         score := 0;
  465.     end;
  466.  
  467. end.